package com.xzbd.gef.model.connection;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

import org.eclipse.draw2d.Bendpoint;

import com.xzbd.constants.CoreConstant;
import com.xzbd.core.gef.Node;

public class AbstractConnectionModel extends Node {

	private static final long serialVersionUID = 1L;

	private ConnectionPort src;
	private ConnectionPort target;
	private String guid;
	protected List<ConnectionBendpoint> constraints = new ArrayList<ConnectionBendpoint>();

	private int lineWidth = 2;

	public static final String PROPERTY_LINE_WIDTH = "p_linewidth";
	public static final String P_CONSTRAINT = "p_constraint";
	public static final String ACNC_SOURCE = "acnc_source";
	public static final String ACNC_TARGET = "acnc_target";

	public AbstractConnectionModel() {
		this.guid = UUID.randomUUID().toString();
	}

	public int getLineWidth() {
		return lineWidth;
	}

	public void setLineWidth(int lineWidth) {
		int oldLineWidth = this.lineWidth;
		this.lineWidth = lineWidth;
		getListeners().firePropertyChange(PROPERTY_LINE_WIDTH, oldLineWidth,
				this.lineWidth);
	}

	public List<ConnectionBendpoint> getConstraints() {
		return constraints;
	}

	public void removeConstraint(int index) {
		ConnectionBendpoint bendpoint = constraints.get(index);
		constraints.remove(index);
		firePropertyChange(P_CONSTRAINT, bendpoint, null);
	}

	public void removeConstraint(Bendpoint bendpoint) {
		constraints.remove(bendpoint);
		firePropertyChange(P_CONSTRAINT, bendpoint, null);
	}

	public void replaceConstraint(int index, ConnectionBendpoint bendpoint) {
		ConnectionBendpoint oldBendpoint = constraints.get(index);
		constraints.set(index, bendpoint);
		firePropertyChange(P_CONSTRAINT, oldBendpoint, bendpoint);
	}

	public void addConstraint(int index, ConnectionBendpoint bendpoint) {
		if (!constraints.contains(bendpoint)) {
			constraints.add(bendpoint);
			firePropertyChange(P_CONSTRAINT, null, bendpoint);
		}
	}

	public void setConstraint(int index, ConnectionBendpoint bendpoint) {
		if (!constraints.contains(bendpoint))
			;
		constraints.set(index, bendpoint);
		firePropertyChange(P_CONSTRAINT, null, bendpoint);
	}

	public void hide(boolean hide) {
		if (!hide) {
			firePropertyChange(CoreConstant.HIDE, null, null);
		} else {
			firePropertyChange(CoreConstant.SHOW, null, null);
		}
	}

	public ConnectionPort getSrc() {
		return src;
	}

	public void setSrc(ConnectionPort src) {
		ConnectionPort oldSrc = src;
		this.src = src;
		firePropertyChange(ACNC_SOURCE, oldSrc, src);
	}

	public ConnectionPort getTarget() {
		return target;
	}

	public void setTarget(ConnectionPort target) {
		ConnectionPort oldTarget = target;
		this.target = target;
		firePropertyChange(ACNC_TARGET, oldTarget, target);
	}

	public void attachSource() {
		List<AbstractConnectionModel> outputs = src.getOutputs();
		if (Objects.isNull(outputs)) {
			return;
		}
		if (outputs.contains(this)) {
			return;
		}
		src.addOut(this);
	}

	public void attachTarget() {
		List<AbstractConnectionModel> inputs = target.getInputs();
		if (Objects.isNull(inputs)) {
			return;
		}
		if (!inputs.contains(this)) {
			target.addIn(this);
		}
	}

	public void deattachSource() {
		List<AbstractConnectionModel> outputs = src.getOutputs();
		if (Objects.isNull(outputs)) {
			return;
		}
		if (!outputs.contains(this)) {
			return;
		}
		src.removeOut(this);
	}

	public void deattachTarget() {
		List<AbstractConnectionModel> inputs = target.getInputs();
		if (Objects.isNull(inputs)) {
			return;
		}
		if (inputs.contains(this)) {
			target.removeInput(this);
		}
	}

	public String getGuid() {
		return guid;
	}

	public void setGuid(String guid) {
		this.guid = guid;
	}

}
